#include "screenrecorder.h"
#include <QDebug>
#include <QApplication>
#include <QScreen>
#include <QNetworkInterface>
#include <QFile>
#include <QTextStream>
#include <QFileInfo>

ScreenRecorder::ScreenRecorder(QObject *parent) : QObject(parent),
    ffmpegProcess(nullptr), statusTimer(nullptr), isRecordingFlag(false), isPausedFlag(false), pausedDuration(0)
{
    // 动态获取实际屏幕分辨率
    QScreen *screen = QApplication::primaryScreen();
    if (screen) {
        resolution = screen->size();
        qDebug() << "检测到屏幕分辨率:" << resolution.width() << "x" << resolution.height();
    } else {
        // 回退到实际检测到的分辨率
        resolution = QSize(1912, 986);
        qDebug() << "使用默认分辨率:" << resolution.width() << "x" << resolution.height();
    }
    
    frameRate = 15;
    bitrate = 500000; // 降低到500Kbps，减少网络压力
    recordingMode = StreamOnly; // 默认仅推流
    outputDirectory = QDir::homePath() + "/电子教室录制";
    currentFileSize = 0;
    
    setupFFmpegProcess();
    setupStatusTimer();
}

ScreenRecorder::~ScreenRecorder()
{
    if (isRecordingFlag) {
        stopRecording();
    }
    
    if (ffmpegProcess) {
        ffmpegProcess->deleteLater();
    }
    
    if (statusTimer) {
        statusTimer->deleteLater();
    }
}

bool ScreenRecorder::initialize()
{
    if (!ffmpegProcess) {
        setupFFmpegProcess();
    }
    
    // 检查FFmpeg是否支持x11grab
    QProcess checkProcess;
    checkProcess.start("ffmpeg", QStringList() << "-f" << "x11grab" << "-list_devices" << "true" << "-i" << "dummy");
    checkProcess.waitForFinished(3000);
    
    if (checkProcess.exitCode() != 0) {
        qDebug() << "警告: FFmpeg可能不支持x11grab，尝试使用其他方法";
    }
    
    // 创建输出目录
    createOutputDirectory();
    
    qDebug() << "屏幕录制器初始化完成";
    return true;
}

void ScreenRecorder::setResolution(const QSize& newResolution)
{
    resolution = newResolution;
}

void ScreenRecorder::setFrameRate(int newFrameRate)
{
    frameRate = newFrameRate;
}

void ScreenRecorder::setBitrate(int newBitrate)
{
    bitrate = newBitrate;
}

void ScreenRecorder::setRecordingMode(RecordingMode mode)
{
    recordingMode = mode;
    qDebug() << "设置录制模式:" << mode;
}

void ScreenRecorder::setOutputDirectory(const QString& directory)
{
    outputDirectory = directory;
    createOutputDirectory();
}

bool ScreenRecorder::startRecording()
{
    if (isRecordingFlag) {
        return false;
    }
    
    qDebug() << "开始屏幕录制，模式:" << recordingMode;
    
    // 先生成文件名
    currentRecordingFile = generateFileName();
    qDebug() << "录制文件路径:" << currentRecordingFile;
    
    // 根据录制模式构建不同的FFmpeg参数
    if (recordingMode == FileOnly || recordingMode == StreamAndFile) {
        buildFileRecordingArguments();
    }
    
    if (recordingMode == StreamOnly || recordingMode == StreamAndFile) {
        buildStreamRecordingArguments();
    }
    
    // 合并参数
    ffmpegArguments.clear();
    if (recordingMode == StreamAndFile) {
        // 同时推流和录制文件，使用复杂的FFmpeg命令
        buildFFmpegArguments();
    } else if (recordingMode == FileOnly) {
        ffmpegArguments = fileArguments;
    } else {
        ffmpegArguments = streamArguments;
    }
    
    // 调试：输出FFmpeg命令（可选）
    // QString command = "ffmpeg " + ffmpegArguments.join(" ");
    // qDebug() << "FFmpeg命令:" << command;
    
    // 启动FFmpeg进程
    ffmpegProcess->start("ffmpeg", ffmpegArguments);
    
    if (ffmpegProcess->waitForStarted(5000)) {
        isRecordingFlag = true;
        isPausedFlag = false;
        recordingStartTime = QDateTime::currentDateTime();
        
        // 如果是推流模式，生成SDP文件
        if (recordingMode == StreamOnly || recordingMode == StreamAndFile) {
            generateSDPFile();
        }
        
        // 启动状态监控定时器
        startStatusTimer();
        
        emit recordingStarted();
        emit statusChanged("录制中");
        qDebug() << "FFmpeg进程启动成功，进程ID:" << ffmpegProcess->processId();
        return true;
    } else {
        qDebug() << "FFmpeg进程启动失败:" << ffmpegProcess->errorString();
        qDebug() << "进程状态:" << ffmpegProcess->state();
        return false;
    }
}

void ScreenRecorder::stopRecording()
{
    if (!isRecordingFlag) {
        return;
    }
    
    qDebug() << "停止屏幕录制...";
    
    // 停止状态监控
    stopStatusTimer();
    
    if (ffmpegProcess && ffmpegProcess->state() == QProcess::Running) {
        // 先尝试优雅停止FFmpeg
        ffmpegProcess->terminate();
        
        // 等待FFmpeg正常退出
        if (ffmpegProcess->waitForFinished(3000)) {
            qDebug() << "FFmpeg进程正常退出";
        } else {
            // 如果3秒内没有停止，再等待2秒
            qDebug() << "FFmpeg进程未在3秒内退出，继续等待...";
            if (!ffmpegProcess->waitForFinished(2000)) {
                // 最后强制终止
                qDebug() << "强制终止FFmpeg进程";
                ffmpegProcess->kill();
                ffmpegProcess->waitForFinished();
            }
        }
    }
    
    isRecordingFlag = false;
    isPausedFlag = false;
    emit recordingStopped();
    emit statusChanged("已停止");
    qDebug() << "屏幕录制已停止";
}

bool ScreenRecorder::isRecording() const
{
    return isRecordingFlag;
}

QString ScreenRecorder::getCurrentRecordingFile() const
{
    return currentRecordingFile;
}

qint64 ScreenRecorder::getRecordingDuration() const
{
    if (!isRecordingFlag) {
        return 0;
    }
    
    // 如果暂停了，返回暂停前的时长
    if (isPausedFlag) {
        return pausedDuration;
    }
    
    return recordingStartTime.msecsTo(QDateTime::currentDateTime());
}

qint64 ScreenRecorder::getFileSize() const
{
    return currentFileSize;
}

QString ScreenRecorder::getRecordingStatus() const
{
    if (!isRecordingFlag) {
        return "未录制";
    }
    if (isPausedFlag) {
        return "已暂停";
    }
    return "录制中";
}

void ScreenRecorder::pauseRecording()
{
    if (!isRecordingFlag || isPausedFlag) {
        return;
    }
    
    qDebug() << "暂停录制...";
    
    // 向FFmpeg发送SIGSTOP信号暂停进程
    if (ffmpegProcess && ffmpegProcess->state() == QProcess::Running) {
        QProcess::execute("kill", QStringList() << "-STOP" << QString::number(ffmpegProcess->processId()));
        qDebug() << "已发送SIGSTOP信号暂停FFmpeg进程";
    }
    
    // 停止状态监控
    stopStatusTimer();
    
    // 记录暂停时的累计时长
    pausedDuration = recordingStartTime.msecsTo(QDateTime::currentDateTime());
    
    isPausedFlag = true;
    emit recordingPaused();
    emit statusChanged("已暂停");
    qDebug() << "录制已暂停，累计时长:" << pausedDuration << "ms";
}

void ScreenRecorder::resumeRecording()
{
    if (!isRecordingFlag || !isPausedFlag) {
        return;
    }
    
    qDebug() << "恢复录制...";
    
    // 使用kill命令发送SIGCONT信号恢复进程
    if (ffmpegProcess && ffmpegProcess->state() == QProcess::Running) {
        QProcess::execute("kill", QStringList() << "-CONT" << QString::number(ffmpegProcess->processId()));
        qDebug() << "已发送SIGCONT信号恢复FFmpeg进程";
        
        // 恢复录制时，调整开始时间以保持时长连续性
        recordingStartTime = QDateTime::currentDateTime().addMSecs(-pausedDuration);
        
        isPausedFlag = false;
        startStatusTimer();
        emit recordingResumed();
        emit statusChanged("录制中");
        qDebug() << "录制已恢复，调整开始时间以保持时长连续性";
    } else {
        qDebug() << "恢复录制失败：FFmpeg进程不存在";
        emit errorOccurred("恢复录制失败：FFmpeg进程不存在");
        isPausedFlag = false;
    }
}

bool ScreenRecorder::isPaused() const
{
    return isPausedFlag;
}



void ScreenRecorder::setupFFmpegProcess()
{
    ffmpegProcess = new QProcess(this);
    
    // 连接FFmpeg进程信号
    connect(ffmpegProcess, &QProcess::finished, this, &ScreenRecorder::onFFmpegFinished);
    connect(ffmpegProcess, &QProcess::errorOccurred, this, &ScreenRecorder::onFFmpegError);
    
    // 连接FFmpeg输出信号，用于捕获错误信息
    connect(ffmpegProcess, &QProcess::readyReadStandardError, this, &ScreenRecorder::onFFmpegErrorOutput);
}

void ScreenRecorder::setupStatusTimer()
{
    statusTimer = new QTimer(this);
    connect(statusTimer, &QTimer::timeout, this, &ScreenRecorder::updateRecordingStatus);
}

void ScreenRecorder::buildFFmpegArguments()
{
    ffmpegArguments.clear();
    
    // 输入：屏幕捕获
    // qDebug() << "WAYLAND_DISPLAY:" << qgetenv("WAYLAND_DISPLAY");
    // qDebug() << "DISPLAY:" << qgetenv("DISPLAY");
    
    // 使用真实屏幕捕获
    // qDebug() << "使用真实屏幕捕获";
    
    // 确保高度是偶数（H.264要求）
    int adjustedHeight = resolution.height();
    if (adjustedHeight % 2 != 0) {
        adjustedHeight = adjustedHeight - 1;  // 减1确保是偶数
        // qDebug() << "调整复杂录制分辨率高度为偶数:" << resolution.width() << "x" << adjustedHeight;
    }
    
    ffmpegArguments << "-f" << "x11grab"
                   << "-s" << QString("%1x%2").arg(resolution.width()).arg(adjustedHeight)
                   << "-r" << QString::number(frameRate)
                   << "-draw_mouse" << "1"
                   << "-i" << ":0.0";
    
    // 根据录制模式添加输出
    if (recordingMode == StreamAndFile) {
        // 同时推流和录制文件 - 使用两个输出
        // 第一个输出：推流（低延迟配置）
        ffmpegArguments << "-map" << "0:v"
                       << "-c:v" << "libx264"
                       << "-preset" << "ultrafast"
                       << "-profile:v" << "baseline"
                       << "-pix_fmt" << "yuv420p"
                       << "-b:v" << QString::number(bitrate)
                       << "-g" << QString::number(frameRate * 2)
                       << "-threads" << "4"
                       << "-f" << "rtp"
                       << "-payload_type" << "96"
                       << "rtp://224.1.1.1:5004"
                       // 第二个输出：文件录制（高质量配置）
                       << "-map" << "0:v"
                       << "-c:v" << "libx264"
                       << "-preset" << "medium"
                       << "-crf" << "23"
                       << "-pix_fmt" << "yuv420p"
                       << "-g" << QString::number(frameRate * 2)
                       << "-threads" << "4"
                       << "-y"
                       << currentRecordingFile;
    } else if (recordingMode == StreamOnly) {
        // 仅推流 - 优化网络传输
        ffmpegArguments << "-c:v" << "libx264"
                       << "-preset" << "ultrafast"
                       << "-profile:v" << "baseline"
                       << "-pix_fmt" << "yuv420p"
                       << "-b:v" << QString::number(bitrate)
                       << "-g" << QString::number(frameRate * 2)
                       << "-threads" << "4"
                       << "-tune" << "zerolatency"           // 零延迟调优
                       << "-x264opts" << "keyint=30:min-keyint=30:no-scenecut=1"  // 固定关键帧间隔
                       << "-f" << "rtp"
                       << "-payload_type" << "96"
                       << "-max_muxing_queue_size" << "1024"  // 增加队列大小
                       << "-fflags" << "+genpts"              // 生成时间戳
                       << "rtp://224.1.1.1:5004";
    } else {
        // 仅录制文件
        ffmpegArguments << "-c:v" << "libx264"
                       << "-preset" << "medium"
                       << "-crf" << "23"
                       << "-pix_fmt" << "yuv420p"
                       << "-g" << QString::number(frameRate * 2)
                       << "-threads" << "4"
                       << "-y"
                       << currentRecordingFile;
    }
}

void ScreenRecorder::buildFileRecordingArguments()
{
    fileArguments.clear();
    
    // 确保高度是偶数（H.264要求）
    int adjustedHeight = resolution.height();
    if (adjustedHeight % 2 != 0) {
        adjustedHeight = adjustedHeight - 1;  // 减1确保是偶数
        // qDebug() << "调整文件录制分辨率高度为偶数:" << resolution.width() << "x" << adjustedHeight;
    }
    
    // 输入：屏幕捕获
    fileArguments << "-f" << "x11grab"
                 << "-s" << QString("%1x%2").arg(resolution.width()).arg(adjustedHeight)
                 << "-r" << QString::number(frameRate)
                 << "-draw_mouse" << "1"
                 << "-i" << ":0.0";
    
    // 编码：H.264高质量配置
    fileArguments << "-c:v" << "libx264"
                 << "-preset" << "medium"      // 平衡质量和速度
                 << "-crf" << "23"             // 恒定质量因子
                 << "-pix_fmt" << "yuv420p"
                 << "-g" << QString::number(frameRate * 2)
                 << "-threads" << "4"
                 << "-y"  // 覆盖输出文件
                 << currentRecordingFile;
}

void ScreenRecorder::buildStreamRecordingArguments()
{
    streamArguments.clear();
    
    // 确保高度是偶数（H.264要求）
    int adjustedHeight = resolution.height();
    if (adjustedHeight % 2 != 0) {
        adjustedHeight = adjustedHeight - 1;  // 减1确保是偶数
        // qDebug() << "调整推流分辨率高度为偶数:" << resolution.width() << "x" << adjustedHeight;
    }
    
    // 输入：屏幕捕获
    streamArguments << "-f" << "x11grab"
                   << "-s" << QString("%1x%2").arg(resolution.width()).arg(adjustedHeight)
                   << "-r" << QString::number(frameRate)
                   << "-draw_mouse" << "1"
                   << "-i" << ":0.0";
    
    // 编码：H.264低延迟配置 - 优化网络传输
    streamArguments << "-c:v" << "libx264"
                   << "-preset" << "ultrafast"
                   << "-profile:v" << "baseline"
                   << "-pix_fmt" << "yuv420p"
                   << "-b:v" << QString::number(bitrate)
                   << "-g" << QString::number(frameRate * 2)
                   << "-threads" << "4"
                   << "-tune" << "zerolatency"           // 零延迟调优
                   << "-x264opts" << "keyint=30:min-keyint=30:no-scenecut=1"  // 固定关键帧间隔
                   << "-f" << "rtp"
                   << "-payload_type" << "96"
                   << "-max_muxing_queue_size" << "1024"  // 增加队列大小
                   << "-fflags" << "+genpts"              // 生成时间戳
                   << "rtp://224.1.1.1:5004";
}

void ScreenRecorder::generateSDPFile()
{
    // 生成SDP文件到共享目录，所有机器都能访问
    QStringList sdpPaths = {
        "/tmp/stream.sdp",                    // Linux临时目录
        "/var/tmp/stream.sdp",                // 系统临时目录
        QDir::homePath() + "/stream.sdp",     // 用户主目录
        QDir::currentPath() + "/stream.sdp"   // 当前目录
    };
    
            for (const QString& sdpPath : sdpPaths) {
            QFile sdpFile(sdpPath);
            if (sdpFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream out(&sdpFile);
                out << "v=0\n";
                out << "o=- 0 0 IN IP4 224.1.1.1\n";
                out << "s=Electronic Classroom Stream\n";
                out << "c=IN IP4 224.1.1.1\n";
                out << "t=0 0\n";
                out << "m=video 5004 RTP/AVP 96\n";
                out << "a=rtpmap:96 H264/90000\n";
                out << "a=recvonly\n";
                sdpFile.close();
                // qDebug() << "SDP文件生成成功:" << sdpPath;
            }
        }
}

QString ScreenRecorder::generateFileName() const
{
    QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss");
    QString fileName = QString("screen_recording_%1.mp4").arg(timestamp);
    return QDir(outputDirectory).filePath(fileName);
}

void ScreenRecorder::createOutputDirectory()
{
    QDir dir(outputDirectory);
    if (!dir.exists()) {
        if (dir.mkpath(".")) {
            qDebug() << "创建输出目录成功:" << outputDirectory;
        } else {
            qDebug() << "创建输出目录失败:" << outputDirectory;
        }
    }
}

void ScreenRecorder::startStatusTimer()
{
    if (statusTimer) {
        statusTimer->start(1000); // 每秒更新一次状态
    }
}

void ScreenRecorder::stopStatusTimer()
{
    if (statusTimer) {
        statusTimer->stop();
    }
}

void ScreenRecorder::updateRecordingStatus()
{
    if (!isRecordingFlag) {
        return;
    }
    
    // 更新录制时长
    qint64 duration = getRecordingDuration();
    emit durationChanged(duration);
    
    // 更新文件大小（如果是文件录制模式）
    if (recordingMode == FileOnly || recordingMode == StreamAndFile) {
        QFileInfo fileInfo(currentRecordingFile);
        if (fileInfo.exists()) {
            qint64 newSize = fileInfo.size();
            if (newSize != currentFileSize) {
                currentFileSize = newSize;
                emit fileSizeChanged(currentFileSize);
            }
        }
    }
}

QString ScreenRecorder::getLocalNetworkIP()
{
    foreach(const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) {
        if (interface.flags().testFlag(QNetworkInterface::IsUp) &&
            !interface.flags().testFlag(QNetworkInterface::IsLoopBack)) {
            foreach(const QNetworkAddressEntry &address, interface.addressEntries()) {
                if (address.ip().protocol() == QAbstractSocket::IPv4Protocol) {
                    return address.ip().toString();
                }
            }
        }
    }
    return "127.0.0.1";
}

void ScreenRecorder::onFFmpegFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    qDebug() << "FFmpeg进程结束，退出码:" << exitCode << "退出状态:" << exitStatus;
    
    // 停止状态监控
    stopStatusTimer();
    
    // 处理FFmpeg退出
    if (exitStatus == QProcess::CrashExit) {
        // 进程崩溃
        emit errorOccurred("FFmpeg进程崩溃");
        isRecordingFlag = false;
        emit recordingStopped();
        emit statusChanged("录制失败");
    } else if (exitCode == 255) {
        // 退出码255通常是用户中断（Ctrl+C或terminate信号），不算错误
        qDebug() << "FFmpeg进程被用户中断，退出码:" << exitCode;
        isRecordingFlag = false;
        emit recordingStopped();
        emit statusChanged("录制已停止");
    } else if (exitCode != 0) {
        // 其他非零退出码
        emit errorOccurred(QString("FFmpeg异常结束，退出码: %1").arg(exitCode));
        isRecordingFlag = false;
        emit recordingStopped();
        emit statusChanged("录制失败");
    } else {
        // 正常退出
        isRecordingFlag = false;
        emit recordingStopped();
        emit statusChanged("录制完成");
        qDebug() << "录制正常完成";
    }
}

void ScreenRecorder::onFFmpegError(QProcess::ProcessError error)
{
    QString errorStr;
    switch (error) {
        case QProcess::FailedToStart:
            errorStr = "进程启动失败";
            break;
        case QProcess::Crashed:
            errorStr = "进程崩溃";
            break;
        case QProcess::Timedout:
            errorStr = "进程超时";
            break;
        default:
            errorStr = "未知错误";
            break;
    }
    
    qDebug() << "FFmpeg进程错误:" << errorStr;
    emit errorOccurred(errorStr);
    emit statusChanged("录制错误");
}

void ScreenRecorder::onFFmpegErrorOutput()
{
    const QString errorOutput = QString::fromUtf8(ffmpegProcess->readAllStandardError());
    
    // 只显示关键错误信息
    if (errorOutput.contains("Network is unreachable")) {
        qDebug() << "FFmpeg错误: 网络不可达，请检查多播配置";
    } else if (errorOutput.contains("Permission denied")) {
        qDebug() << "FFmpeg错误: 权限被拒绝";
    } else if (errorOutput.contains("Connection refused")) {
        qDebug() << "FFmpeg错误: 连接被拒绝";
    } else if (errorOutput.contains("Address already in use")) {
        qDebug() << "FFmpeg错误: 端口被占用";
    }
}
